﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Exchange.WebServices.Data;
using System.IO;

namespace Alex.Library.Net.Mail {
    /// <summary>
    /// 利用Exchange Server发邮件
    /// </summary>
    public class ExchangeMail : IMail {

        private ExchangeService service;
        private EmailMessage msg;
        private long maxAttachmentSize = 10485760; //10M
        private string[ ] attachmentFileExts;
        private List<string> attachmentFileNames;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="exchangeVersion">Exchange Server版本</param>
        public ExchangeMail ( ExchangeVersion exchangeVersion ) {
            service = new ExchangeService ( exchangeVersion );
            msg = new EmailMessage ( service );
            this.attachmentFileNames = new List<string> ();            
        }
        /// <summary>
        /// 设置Exchange Server地址
        /// </summary>
        /// <param name="address"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public IMail SetHost ( string address ) {
            service.Url = new Uri ( address );
            return this;
        }

        public IMail SetPort ( int port ) {
            throw new Exception ( "端口应该包含在Host地址中，使用SetHost方法设置地址和端口." );
        }

        public IMail SetCredential ( string userName, string password ) {
            if ( userName.Contains ( @"\" ) ) {
                string[ ] s = userName.Split ( '\\' );
                string domain = s[ 0 ];
                string uname = s[ 1 ];
                service.Credentials = new WebCredentials ( uname, password, domain );
            } else {
                service.Credentials = new WebCredentials ( userName, password );
            }
            return this;
        }

        public IMail SetSender ( string senderAddress ) {
            //service.AutodiscoverUrl ( senderAddress );
            msg.From = new EmailAddress ( senderAddress );
            return this;
        }

        public IMail AddRecipient ( string recipientAddress ) {
            msg.ToRecipients.Add ( recipientAddress );
            return this;
        }

        public IMail AddCc ( string ccAddress ) {
            msg.CcRecipients.Add ( ccAddress );
            return this;
        }

        public IMail SetSubject ( string subject ) {
            msg.Subject = subject;
            return this;
        }

        public IMail SetSubjectEncoding ( Encoding encoding ) {
            return this;
        }

        public IMail SetBody ( string body, bool isHTML = true ) {
            msg.Body = new MessageBody ();
            msg.Body.Text = body;
            msg.Body.BodyType = isHTML ? BodyType.HTML : BodyType.Text;

            return this;
        }

        public IMail SetBodyEncoding ( Encoding encoding ) {
            return this;
        }

        public IMail SetPriority ( MyMailPriority priority ) {
            switch ( priority ) {
                case MyMailPriority.High:
                    msg.Importance = Importance.High;
                    break;
                case MyMailPriority.Low:
                    msg.Importance = Importance.Low;
                    break;
                case MyMailPriority.Normal:
                    msg.Importance = Importance.Normal;
                    break;
            }
            return this;
        }

        public IMail SetSslEnabled ( bool enabled ) {

            return this;
        }

        public IMail SetAttachmentMaxSize ( long maxSize ) {
            this.maxAttachmentSize = maxSize;
            return this;
        }

        public IMail SetAttachmentFileExts ( string[ ] fileExts ) {
            this.attachmentFileExts = fileExts;
            return this;
        }

        public IMail AddAttachment ( string filename ) {
            this.attachmentFileNames.Add ( filename );
            msg.Attachments.AddFileAttachment ( filename );
            return this;
        }

        public IMail AddAttachment ( string filename, string mediaType ) {
            
            return AddAttachment ( filename );
        }

        public IMail Send () {
            try {
                Valid ();
                msg.SendAndSaveCopy ();                
                return this;
            } catch ( Exception ex ) {
                throw ex;
            }
        }

        private void Valid () {
            if ( service.Url == null ) {
                throw new Exception ( "缺少Exchange服务器地址." );
            }
            if ( msg.From == null || service.Credentials == null ) {
                throw new Exception ( "缺少发件人地址." );
            }
            if ( msg.ToRecipients.Count == 0 ) {
                throw new Exception ( "缺少收件人地址." );
            }
            if ( msg.HasAttachments ) {
                long totalSize = 0;
                foreach ( Attachment attachment in msg.Attachments ) {
                    totalSize += attachment.Size;
                }
                int maxSize = ( int ) ( this.maxAttachmentSize / 1024 / 1024 );
                if ( totalSize > this.maxAttachmentSize ) {
                    throw new Exception ( "附件大小不能超过" + maxSize + "M." );
                }
                if ( this.attachmentFileExts != null && this.attachmentFileExts.Length > 0 ) {
                    string fileExt = "";
                    foreach ( string filename in this.attachmentFileNames ) {
                        fileExt = Path.GetExtension ( filename );
                        if ( !this.attachmentFileExts.Contains ( fileExt,
                            StringComparer.OrdinalIgnoreCase ) ) {
                            throw new Exception ( "只允许上传" + String.Join ( "|", this.attachmentFileExts ) + "的格式附件." );
                        }
                    }
                }
            }
        }
    }
}
